package com.ys.web.sys.phone;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.ys.base.BaseConstants;
import com.ys.base.EnumType;
import com.ys.utils.aliyun.AliyunSmsUtils;
import com.ys.utils.base.http.ResponseHandler;
import com.ys.utils.base.j2se.DateHandler;
import com.ys.utils.base.j2se.Logger;
import com.ys.utils.base.j2se.StringHandler;
import com.ys.utils.pay.Result;
import com.ys.utils.redis.Redis;
import com.ys.utils.redis.key.UserKey;
import com.ys.utils.spring.config.SystemError;
import com.ys.utils.spring.properties.Config;
import com.ys.web.user.login.LoginInfo;
import com.ys.web.user.login.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @program: tbyy-app->PhoneController
 * @Auther: 王伟
 * @Date: 2019/11/7 17:21
 * @Description: 短信及电话信息
 */
@RestController
@RequestMapping("/system/phone/")
@EnableAutoConfiguration
public class PhoneController {
    @Autowired
    private LoginService loginService;

    @RequestMapping("verify")
    @SuppressWarnings("all")
    public String verify(@RequestAttribute String ip,@RequestParam(defaultValue = "1") int type, @RequestParam(defaultValue = "")String phone) {
        if(StringHandler.isEmpty(phone))
            SystemError.wrapBs("500", "请填写手机号");
        LoginInfo loginInfo = loginService.infoByPhone(phone);
        if (StringHandler.isNotEmpty(loginInfo)) {
            if (type == 1 && StringHandler.isNotEmpty(loginInfo.getOpenId())) {
                SystemError.wrapBs("500", "该手机号已绑定微信");
            } else if (type == 2 && StringHandler.isNotEmpty(loginInfo.getAppleId())) {
                SystemError.wrapBs("500", "该手机号已绑定苹果");
            }
        }
//        if(Config.pp.get("phone.black").contains(phone)){
//            SystemError.wrapBs(EnumType.ResponseCode.ILLEGAL.getCode(), "系统繁忙");
//        }
        return this.sendSMSPost(ip,phone,1);
    }

    @RequestMapping("passVerify")
    @SuppressWarnings("all")
    public String verify(@RequestAttribute String uid,@RequestAttribute String ip,@RequestParam(defaultValue = "1") int type) {
        LoginInfo loginInfo = loginService.infoByUid(uid);
        return this.sendSMSPost(ip,loginInfo.getPhone(),type);
    }

    /**
     *
     * @param phone
     * @param type  1登录验证码  2支付密码修改验证码
     * @return
     */
    @RequestMapping("sendSMS")
    @SuppressWarnings("all")
    public String sendSMS(@RequestAttribute String ip,String phone,@RequestParam(defaultValue = "1") int type) {
        return this.sendSMSPost(ip,phone,type);
    }
    public String sendSMSPost(String ip,String phone,int type) {
        if(Config.pp.get("phone.black").contains(phone)){
            SystemError.wrapBs(EnumType.ResponseCode.ILLEGAL.getCode(), "系统繁忙");
        }
        String key = UserKey.codeByPhone(phone);
        String countKey = UserKey.smsCountByDay(phone);
        String countIpKey = UserKey.smsCountByDay(ip);
//        if (!Logger.isOnline()) {
//            Redis.str.set(key, "123456", 300);
//            return ResponseHandler.success();
//        }
//        if (phone.equals("88888888888")) {
//            Redis.str.set(key, "@#%#(*", 300);
//            return ResponseHandler.success();
//        }
        if(Boolean.parseBoolean(Config.pp.getOrDefault("regist.sms.switch","false"))){
            Redis.str.set(key, "123456", 300);
            return ResponseHandler.success();
        }
        Result<?> result;
        //0.判断当日是否达到上限
        result = checkTodayStint(countKey);
        if (!result.success()) {
            SystemError.wrapBs("500", result.getMessage());
        }
        //1.判断当日ip是否达到上限
        result = checkTodayIpint(countIpKey);
        if (!result.success()) {
            SystemError.wrapBs("500", result.getMessage());
        }
        result = checkIp(phone);
        if (!result.success()) {
            SystemError.wrapBs("500", result.getMessage());
        }

        try {
//            if(Redis.key.exists(key)){
//                return ResponseHandler.error(6001,"短信获取太频繁，请稍后再试");
//            }
            Integer code = new Random().nextInt(899999) + 100000;
            //发送短信
            Map<String, Object> msgMap = new HashMap<>();
            msgMap.put("code", code);
            try {
                SendSmsResponse sendSmsResponse = AliyunSmsUtils.sendMsg(type==1?Config.pp.get("ys.sms.code.id"):"SMS_249095097", phone, JSON.toJSONString(msgMap));
                if (!sendSmsResponse.getCode().equals("OK")) {
                    return ResponseHandler.error("500", "验证码发送失败，请重试");
//                    return ResponseHandler.error("500", sendSmsResponse.getMessage());
                } else {
                    //验证码写入redis
                    Redis.str.set(key, StringHandler.getString(code), 300);
                    long ds = DateHandler.dayMillSeconds(2);
                    Redis.key.increment(countKey);
                    Redis.key.increment(countIpKey);
                    Redis.key.setKeyTimeout(countKey,ds);
                    Redis.key.setKeyTimeout(countIpKey,ds);
                }
            } catch (ClientException e) {
                SystemError.wrapBs("6001","短信发送异常");
            }

        } catch (Exception e) {
            Logger.error("发送短信失败",e);
            return ResponseHandler.error("6001", "发送失败");
        }

        return ResponseHandler.success(Boolean.parseBoolean(Config.pp.getOrDefault(BaseConstants.SwitchConstants.SWITCH_INVITE_CODE, "false")));
//        LoginInfo loginInfo = loginService.infoByPhone(phone);
//        return ResponseHandler.success(
//                StringHandler.isEmpty(loginInfo)
//                        && Boolean.parseBoolean(Config.pp.getOrDefault(BaseConstants.SwitchConstants.SWITCH_INVITE_CODE, "false")));
    }

    /**
     * 验证今日短信上限
     *
     * @return
     */
    private Result<?> checkTodayStint(String key) {
        // 获取今日已发送短信次数
        String todaySendTimesObj = Redis.str.get(key);
        long todaySendTimes = 0;
        if (StringHandler.isNotEmpty(todaySendTimesObj)) {
            todaySendTimes = StringHandler.getLong(todaySendTimesObj);
            long sendSmTotalNum = StringHandler.getLong(Config.pp.getOrDefault("custom.sms.sendSmTotal", "10"));
            if (todaySendTimes >= sendSmTotalNum) {
                return Result.newFailure(-1, "今日发送短信数已达上限，请明日再试");
            }
        }
        return Result.newSuccess(todaySendTimes);
    }

    /**
     * 判断当日ip是否达到上限
     * @param key
     * @return
     */
    private Result<?> checkTodayIpint(String key) {
        // 获取今日已发送短信次数
        String todaySendTimesObj = Redis.str.get(key);
        long todaySendTimes = 0;
        if (StringHandler.isNotEmpty(todaySendTimesObj)) {
            todaySendTimes = StringHandler.getLong(todaySendTimesObj);
            long sendSmTotalNum = StringHandler.getLong(Config.pp.getOrDefault("custom.sms.sendSms.total.ip", "10"));
            if (todaySendTimes >= sendSmTotalNum) {
                return Result.newFailure(-1, "今日发送短信数已达上限，请明日再试");
            }
        }
        return Result.newSuccess(todaySendTimes);
    }
    /**
     * 验证同手机发送短信间隔
     *
     * @param phone
     * @return
     */
    private Result<?> checkIp(String phone) {
        // 获取上次发送短信时间
        Object ipLastSendTimeObj = Redis.str.get("sendSm:" + phone);
        long currentTime = System.currentTimeMillis()/1000;
        String sendSmIntervalTimeSameIp = Config.pp.getOrDefault("custom.sms.sendSmIntervalTimeSameIp", "120");
        if (StringHandler.isNotEmpty(ipLastSendTimeObj)) {
            long ipLastSendTime = Long.parseLong(ipLastSendTimeObj + "");
            if (currentTime - ipLastSendTime < StringHandler.getLong(sendSmIntervalTimeSameIp)) {
                return Result.newFailure(-1, "短信发送过于频繁，请稍后再试");
            }
        }
        // 记录当前ip本次发送短信时间
        Redis.str.set("sendSm:" + phone, currentTime + "", StringHandler.getInt(sendSmIntervalTimeSameIp));
        return Result.newSuccess();
    }
}
